package com.db.mongodb;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.WriteResult;
import com.mongodb.util.JSON;
import com.spider.util.JsonMapper;

public class MMongoDB {

	public static JsonMapper jsonMapper = JsonMapper.buildNonNullMapper();
	private DB db = MongoDBUtil.mongoDB;
	private static int EXEUCTE_FALSE=-1;
	private static int EXEUCTE_SUCCESS=1;
	
	// -----------------create index----------
	public void createIndex(String table, String fieldName) {
		DBCollection collection = getCollection(table);
		collection.createIndex(new BasicDBObject(fieldName, 1));
	}

	// -----------------Save---------------------

	@SuppressWarnings("unchecked")
	public <T> T save(String table, T entity) {
		DBCollection collection = getCollection(table);
		String json = jsonMapper.toJson(entity);
		Object parse = JSON.parse(json);
		collection.insert((DBObject) parse);
		return (T) jsonMapper.fromJson(parse.toString(), entity.getClass());
	}

	public <T> void save(String table, List<T> list) {
		DBCollection collection = getCollection(table);
		List<DBObject> objList = new ArrayList<DBObject>();
		String json = null;
		Object parse = null;
		for (T entity : list) {
			json = jsonMapper.toJson(entity);
			parse = JSON.parse(json);
			objList.add((DBObject) parse);
		}
		collection.insert(objList);
	}

	// -----------------Remove---------------------

	public int remove(String table, Object entity) {
		DBCollection collection = getCollection(table);
		String json = jsonMapper.toJson(entity);
		Object parse = JSON.parse(json);
		WriteResult result = collection.remove((DBObject) parse);
		return result.getN();
	}

	public int removeAll(String table) {
		DBCollection collection = getCollection(table);
		WriteResult result = collection.remove((DBObject) JSON.parse("{}"));
		return result.getN();
	}
	
	public <T> int removeList(String table, List<T> entity) {
		if(entity!=null && entity.size() > 0){
			DBCollection collection = getCollection(table);
			String json = null;
			Object parse = null;
			for(T en : entity){
				json = jsonMapper.toJson(en);
				parse = JSON.parse(json);
				collection.remove((DBObject) parse);
			}
			return EXEUCTE_SUCCESS;
		}else{
			return EXEUCTE_FALSE;
		}
		
	}

	// -----------------Update---------------------

	public int update(String table, Object query, Object $new) {
		DBCollection collection = getCollection(table);
		Object parse_query = JSON.parse(jsonMapper.toJson(query));
		Object parse_new = JSON.parse(jsonMapper.toJson($new));
		WriteResult update = collection.update((DBObject) parse_query,
				(DBObject) parse_new);
		return update.getN();
	}

	// -----------------Select one---------------------

	@SuppressWarnings("unchecked")
	public <T> T findOne(String table, T query) {
		DBObject o = db.getCollection(table).findOne(
				(DBObject) JSON.parse(jsonMapper.toJson(query)));
		if (o == null)
			return null;
		return (T) jsonMapper.fromJson(o.toString(), query.getClass());
	}

	@SuppressWarnings("unchecked")
	public <T> T findOne(String table, T query, T fields) {
		DBObject o = db.getCollection(table).findOne(
				(DBObject) JSON.parse(jsonMapper.toJson(query)),
				(DBObject) JSON.parse(jsonMapper.toJson(fields)));
		if (o == null)
			return null;
		return (T) jsonMapper.fromJson(o.toString(), query.getClass());
	}

	public <T> T findOne(String table, Class<T> clazz) {
		DBObject o = db.getCollection(table).findOne();
		if (o == null)
			return null;
		return (T) jsonMapper.fromJson(o.toString(), clazz);
	}

	public <T> T findOneByIndex(String table, Class<T> clazz, int index) {
		DBCollection collection = getCollection(table);
		DBCursor cursor = collection.find().skip(index).limit(1);
		if (cursor.hasNext()) {
			DBObject next = cursor.next();
			T fromJson = (T) jsonMapper.fromJson(next.toString(), clazz);
			return fromJson;
		}
		return null;
	}

	// -----------------find lit by page -------------------
	public <T> List<T> findListByPage(String table, T query, T fields,T sort,
			Class<T> clazz, int endPage) {
		DBCollection collection = getCollection(table);
		DBCursor cursor = collection.find(
				(DBObject) JSON.parse(jsonMapper.toJson(query)),
				(DBObject) JSON.parse(jsonMapper.toJson(fields))).sort((DBObject)JSON.parse(jsonMapper.toJson(sort))).limit(endPage);
		List<T> result = new ArrayList<T>();
		if (cursor.hasNext()) {
			DBObject next = cursor.next();
			T fromJson = (T) jsonMapper.fromJson(next.toString(), clazz);
			result.add(fromJson);
		}
		return result;
	}

	// -----------------find lit by page  -------------------

	// -----------------pop one---------------------

	public <T> T pop(String table, Class<T> clazz) {
		DBObject o = null;
		DBCollection collection = getCollection(table);
		synchronized (this) {
			o = collection.findOne();
			if (o == null)
				return null;
			collection.remove(o);
		}
		return (T) jsonMapper.fromJson(o.toString(), clazz);
	}

	public DBCollection getCollection(String table) {
		return db.getCollection(table);
	}

	// -----------------find with json---------------------

	public <T> Iterator<T> find(String table, String json, Class<T> clazz) {
		DBCursor curosr = db.getCollection(table).find(
				(DBObject) JSON.parse(json));
		Iterator<T> mongoIterator = new MongoIterator<T>(curosr, clazz);
		return mongoIterator;
	}

	public <T> Iterator<T> find(String table, String query_json,
			String fields_josn, Class<T> clazz) {
		DBCursor curosr = db.getCollection(table).find(
				(DBObject) JSON.parse(query_json),
				(DBObject) JSON.parse(fields_josn));
		Iterator<T> mongoIterator = new MongoIterator<T>(curosr, clazz);
		return mongoIterator;
	}

	// -----------------Select with javabean cretira---------------------

	public <T> Iterator<T> getIterator(String table, T cretira) {
		String json_cretira = jsonMapper.toJson(cretira);
		Object parse = JSON.parse(json_cretira);
		DBCursor curosr = db.getCollection(table).find((DBObject) parse);
		Iterator<T> mongoIterator = new MongoIterator<T>(curosr,
				cretira.getClass());
		return mongoIterator;
	}

	// -----------------Select All---------------------

	public <T> Iterator<T> getIterator(String table, Class<T> clazz) {
		DBCursor curosr = db.getCollection(table).find();
		Iterator<T> mongoIterator = new MongoIterator<T>(curosr, clazz);
		return mongoIterator;
	}

	// -----------------MongoIterator------------
	public static class MongoIterator<T> implements Iterator<T> {
		private DBCursor dbCursor;
		private Class<?> clazz;

		public MongoIterator(DBCursor dbCursor, Class<?> clazz) {
			this.dbCursor = dbCursor;
			this.clazz = clazz;
		}

		public boolean hasNext() {
			boolean hasNext = dbCursor.hasNext();
			return hasNext;
		}

		@SuppressWarnings("unchecked")
		public T next() {
			DBObject next = dbCursor.next();
			T fromJson = (T) jsonMapper.fromJson(next.toString(), clazz);
			return fromJson;
		}

		public void remove() {
			dbCursor.remove();
		}
	}
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//